#pragma once

#include <string>
#include <render/Others/PerseusLibDefines.h>
#include <render/Primitives/Image.h>

namespace pwp {

class ImageRender;
class Renderer3DObject;
class Renderer3DView;
class ModelH;
class ModelFace;

class DrawingEngine {
public:
  enum RenderingType {RENDERING_FILL, RENDERING_WIREFRAME};

  float scale = 1.0f;

  static DrawingEngine* Instance(void) {
    if (instance == NULL) instance = new DrawingEngine();
    return instance;
  }

  void Draw(
    Renderer3DObject* object, Renderer3DView* view, const float* pose,
    ImageRender* imageRender, bool clearImage = true);

  bool CalcBodyPoint(
    int x, int y, 
    Renderer3DView* view, ImageRender* imageRender,
    float* x_unproj);

  DrawingEngine();
  ~DrawingEngine();

private:
  VFLOAT projectionMatrix[16], modelViewMatrix[16], pmMatrix[16], buffer[4];

  void applyCoordinateTransform(Renderer3DView* view, Renderer3DObject* object, float* pmMatrix);

  void drawFaceEdges(ImageUChar* imageRender, ModelFace* currentFace, ModelH* drawingModel, VBYTE color, int* roiGenerated);
  void drawFaceFilled(ImageRender* imageRender, ModelFace& currentFace, ModelH* drawingModel, VBYTE color);

  void drawFilled(ImageRender* imageFill, ModelH* drawingModel, int objectId);
  void ComputeAndSetPMMatrices(Renderer3DObject* object, Renderer3DView* view, const float* pose);

  static DrawingEngine* instance;
};

}
